import shlex
import sys
from sys import argv

asmfile = argv[1]
romsize = int(argv[2])

with open(asmfile, "r",errors='ignore') as f:
    body= f.read()


labels = {}
globals = {}
next_global = 0
fixups = []
code = []

# 存储指令的map
# -------------------------------------------------------------
# 0: reg    pp   ; acc=pp
# 1: output pp   ; o_portid = pp, o_port = ram[pp] 
# 2: input  pp   ; o_portid = pp, ram[pp] = i_port
# 3: ldr    pp   ; ram[acc] = ram[pp]
# 4: ldi    dd   ; ram[acc] = dd 
# 5: add    pp   ; ram[acc] = ram[acc] + ram[pp]
# 6: sub    pp   ; ram[acc] = ram[acc] - ram[pp]
# 7: and    pp   ; ram[acc] = ram[acc] & ram[pp]
# 8: or     pp   ; ram[acc] = ram[acc] | ram[pp]
# 9: sl     pp   ; ram[pp]    = ram[pp] << 1
# a: sr     pp   ; ram[pp]    = ram[pp] >> 1
# b: jmp    pp   ; pc = pp   
# c: jmpz   pp   ; ram[acc]==0 ? pc=pp : pc = pc+1
# -------------------------------------------------------------
instruction_map = {
    'reg': 0x000,
    'output': 0x100,
    'input': 0x200,
    'ldr': 0x300,
    'ldi': 0x400,
    'add': 0x500,
    'sub': 0x600,
    'and': 0x700,
    'or': 0x800,
    'sl': 0x900,
    'sr': 0xa00,
    'jmp': 0xb00,
    'jmpz': 0xc00,
    'nop': 0x000
}

lexer = shlex.shlex(body)

lexer.commenters = '#'
lexer.commenters += ';'
lexer.wordchars += '_:-'



def GetValue():
    operand = lexer.get_token()
    if operand.isdigit() :
        return int(operand)
    else:
        return globals[operand] 
    
while True:
    token = lexer.get_token()
    if token == '':
        break

    if token[-1] == ':':
        # define label
        token = token[:-1]
        if token in labels:
            raise Exception(str(lexer.lineno) + ': redefined label ' + token)
        else:
            labels[token] = len(code) 
    elif token == 'res':
        # reserve data
        globals[lexer.get_token()] = next_global
        lookahead = lexer.get_token()
        if lookahead == ',':
            next_global += int(lexer.get_token())
        else:
            lexer.push_token(lookahead)
            next_global += 1
    # ----------------------
    elif  token == 'jmp':
    # Branch if accumulator less than zero
        target = lexer.get_token()
        if target in labels:
            code += [instruction_map['jmp']| labels[target]]
        else:
            fixups = [(len(code), target)]
            code += [instruction_map['jmp']]
    elif  token == 'jmpz':
        target = lexer.get_token()
        if target in labels:
            code += [instruction_map['jmpz'] | labels[target]]
        else:
            fixups = [(len(code), target)]
            code += [instruction_map['jmpz']]
    # 若token在instruction_map ，则执行以下
    elif token in instruction_map:
        value = GetValue()
        code += [instruction_map[token] | value]

    else:
        raise Exception(str(lexer.lineno)  + " : bad instruction -> " + token )

for addr, label in fixups:
    code[addr] = (code[addr] & 0xf00) | (labels[label] & 0xff)

cnt = 0
for x in code:
    print('%03x' % x)
    cnt=cnt+1

while True :
    if(cnt<romsize):
        print('000')
        cnt=cnt+1
    else:
        break 

